package com.qn.visitor.service;

import com.alibaba.fastjson2.JSON;
import com.qn.common.base.BaseServiceImpl;
import com.qn.core.exception.QnDelimitException;
import com.qn.visitor.analyze.AnalyzeEngine;
import com.qn.visitor.analyze.filter.FilterContext;
import com.qn.visitor.entity.IpAddressRecord;
import com.qn.visitor.entity.UserAgentRecord;
import com.qn.visitor.entity.UserLanguageRecord;
import com.qn.visitor.entity.VisitorRecord;
import com.qn.visitor.intercept.InterceptContext;
import com.qn.visitor.model.UserVisitorRequest;
import com.qn.visitor.model.bo.AnalyzeBo;
import com.qn.visitor.model.bo.analyze.ClientLanguageModel;
import com.qn.visitor.model.bo.analyze.IpAddressModel;
import com.qn.visitor.model.bo.analyze.UserAgentModel;
import com.qn.visitor.model.bo.intercept.InterceptResult;
import com.qn.visitor.model.bo.intercept.InterceptRule;
import com.qn.visitor.model.bo.intercept.InterceptSource;
import com.qn.visitor.vo.AnalyzeVo;
import com.qn.visitor.analyze.ipaddressr.IpAddressrProperties;
import com.qn.visitor.write.IpAddressrWrite;
import com.qn.visitor.write.UserAgentWrite;
import com.qn.visitor.write.UserLanguageWrite;
import com.qn.visitor.write.WriteContext;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Date;
import java.util.List;
/**
 * qingniu-cloud user source analysis
 *
 * @Author: TXG
 * @Date: 2024/6/11
 * @Version V0.0.2
 */
@DubboService(version = "1.0.0")
public class UserAnalysisServiceImpl
        extends BaseServiceImpl<VisitorRecord>
        implements UserAnalysisService {
    @Autowired
    AnalyzeEngine analyzeEngine;
    @Autowired
    IpAddressrProperties properties;
    @Autowired
    FilterContext filterContext;
    @Autowired
    WriteContext writeContext;
    @Autowired
    InterceptContext context;
    @Autowired
    FeatureBlacklistService featureBlacklistService;
    
    @Override
    public AnalyzeVo analyze(UserVisitorRequest uvr) throws Exception {
        //TODO：数据分析
        AnalyzeBo uvrBo = analyzeEngine.execute(uvr);
        //TODO: 当cookie中的VID丢失后跟其他指纹从新获取一个
        //TODO：存储数据
        Integer visitorId = saveVisitorAnalyze(uvrBo);
        //TODO:获取拦截引擎需要的参数
        InterceptSource source=analyzeEngine.getSource(uvrBo);

        //TODO：调用防御返回对应的状态
        //获取规则
        InterceptRule rule = featureBlacklistService.getBlackRule();
        //执行黑白名单判断
        InterceptResult result = context.intercept(source, rule);
        //返回包装
        return new AnalyzeVo(visitorId, result.getState(), result.getInterceptType());
    }

    /**
     * 访问数据写入
     *
     * @param uvrBo 结论解析对象 @Transactional
     * @return 本次访问序列号
     * @throws Exception 数据一次
     */
    
    @Override
    public Integer saveVisitorAnalyze(AnalyzeBo uvrBo) throws Exception {
        //访问
        Integer visitorId = visitorAdd(uvrBo);
        //UserAgent
        userAgentAdd(uvrBo);
        //客户端语言
        languageAdd(uvrBo);
        //IP
        ipAddressrAdd(uvrBo);
        return visitorId;
    }

    /**
     * 用户访问数据写入
     *
     * @param uvrBo 结论解析对象
     */
    private Integer visitorAdd(AnalyzeBo uvrBo) throws QnDelimitException {
        VisitorRecord record = new VisitorRecord();
        UserVisitorRequest uvr = uvrBo.getUvr();
        record.setDId(uvrBo.getUvr().getDId());
        record.setHost(uvr.getHost());
        record.setPath(uvr.getPath());
        record.setUrl(uvr.getUrl());
        record.setReferer(uvr.getReferer());
        record.setUaHash(uvrBo.getUaHash());
        record.setClHash(uvrBo.getClHash());
        record.setIp4(uvrBo.getIpHash());
        record.setCkf(uvr.getCkf());
        record.setJa4(uvr.getJa4());
        record.setH2(uvr.getH2());
        record.setTimeZone(uvr.getTimeZone());
        record.setNewTime(new Date());
        writeContext.getVisitorWriteInstanc().add(record);
        return record.getId();
    }

    /**
     * 用户代理数据写入
     *
     * @param uvrBo 结论解析对象
     */
    
    private void userAgentAdd(AnalyzeBo uvrBo) throws Exception {
        UserAgentModel ua = uvrBo.getUa();
        if (ua == null) {
            return;
        }
        UserAgentWrite write= writeContext.getUserAgentWriteInstanc();
        String hash = write.getHash(uvrBo.getUaHash());
        if (hash != null) {
            filterContext.uaInstance().add(hash);
            return;
        }
        UserAgentRecord record = new UserAgentRecord();
        record.setHash(uvrBo.getUaHash());
        record.setSource(JSON.toJSONString(uvrBo.getUvr().getUserAgent()));
        record.setDeviceBrand(ua.getDeviceBrand());
        record.setDeviceClass(ua.getDeviceClass());
        record.setDeviceVersion(ua.getDeviceVersion());
        record.setSystemName(ua.getSystemName());
        record.setSystemClass(ua.getSystemClass());
        record.setSystemVersion(ua.getSystemVersion());
        record.setBrowserName(ua.getBrowserName());
        record.setBrowserType(ua.getBrowserType());
        record.setBrowserVersion(ua.getBrowserVersion());
        record.setNewTime(new Date());
        write.add(record);
        filterContext.uaInstance().add(hash);
    }

    /**
     * 客户端语言写入
     *
     * @param uvrBo 结论解析对象
     */
    private void languageAdd(AnalyzeBo uvrBo) throws Exception {
        List<ClientLanguageModel> cl = uvrBo.getCl();
        if (cl == null) {
            return;
        }
        UserLanguageWrite write= writeContext.getsUerLanguageWriteInstanc();
        String hash = write.getHash(uvrBo.getClHash());
        if (hash != null) {
            filterContext.clInstance().add(hash);
            return;
        }
        UserLanguageRecord record = new UserLanguageRecord();
        record.setHash(uvrBo.getClHash());
        record.setSource(uvrBo.getUvr().getClientLanguage());
        record.setFirst(cl.get(0).getLanguage());
        record.setResult(JSON.toJSONString(cl));
        record.setNewTime(new Date());
        write.add(record);
        filterContext.clInstance().add(hash);
    }

    /**
     * IP数据写入
     *
     * @param uvrBo 结论解析对象
     */
    private void ipAddressrAdd(AnalyzeBo uvrBo) throws Exception {
        IpAddressModel ip = uvrBo.getIp();
        if (ip == null) {
            return;
        }
        IpAddressrWrite write=writeContext.getIpAddressrWriteInstanc();
        String hash = write.getHash(uvrBo.getIpHash(), properties.getIpAddressrTypeInt());
        if (hash != null) {
            filterContext.ipInstance().add(hash);
            return;
        }
        IpAddressRecord record = new IpAddressRecord();
        record.setIp4(uvrBo.getIpHash());
        record.setIpSource(properties.getIpAddressrTypeInt());
        record.setContinent(ip.getContinent());
        record.setContinentCode(ip.getContinentCode());
        record.setCountry(ip.getCountry());
        record.setCountryCode(ip.getCountryCode());
        record.setRegion(ip.getRegion());
        record.setRegionCode(ip.getRegionCode());
        record.setCity(ip.getCity());
        record.setLatitude(ip.getLatitude());
        record.setLongitude(ip.getLongitude());
        record.setContinentCode(ip.getContinentCode());
        record.setConnectionAsn(ip.getConnectionAsn());
        record.setTimezoneId(ip.getTimezoneId());
        record.setTimezoneCurrentTime(ip.getTimezoneCurrentTime());
        record.setSecurityAnonymous(ip.getSecurityAnonymous());
        record.setSecurityProxy(ip.getSecurityProxy());
        record.setSecurityHosting(ip.getSecurityHosting());
        record.setSecurityVpn(ip.getSecurityVpn());
        record.setSecurityTor(ip.getSecurityTor());
        record.setNewTime(new Date());
        write.add(record);
        filterContext.ipInstance().add(hash);
    }
}